﻿using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.DatabaseServices;

namespace AutoCADDotNetLibrary
{
    /// <summary>
    /// 组扩展
    /// </summary>
    public static class GroupExtention
    {
        /// <summary>
        /// 添加系列下的新组
        /// </summary>
        /// <param name="db">dwg数据库</param>
        /// <param name="groupName">组名称（系列名，代表一个系列，例如输入A,实际为A1,下一个组为A2）</param>
        /// <param name="ids">实体id集</param>
        /// <returns>组</returns>
        public static Group AddSeriesNumGroup(this Database db, string groupName, params ObjectId[] ids)
        {
            Transaction trans = db.TransactionManager.TopTransaction;
            DBDictionary groupDict = (DBDictionary)trans.GetObject(db.GroupDictionaryId, OpenMode.ForWrite);

            int i = 1;
            while (groupDict.Contains(groupName + i))
            {
                i++;
            }
            Group group = new Group(groupName + i, true);
            groupDict.SetAt(groupName + i, group);
            trans.AddNewlyCreatedDBObject(group, true);
            group.Append(new ObjectIdCollection(ids));

            return group;
        }

        /// <summary>
        /// 添加新的组
        /// </summary>
        /// <param name="db">dwg数据库</param>
        /// <param name="groupName">组名称</param>
        /// <param name="ids">实体id集</param>
        /// <returns>组</returns>
        public static Group AddGroup(this Database db, string groupName, params ObjectId[] ids)
        {
            Transaction trans = db.TransactionManager.TopTransaction;
            DBDictionary groupDict = (DBDictionary)trans.GetObject(db.GroupDictionaryId, OpenMode.ForWrite);

            if (groupDict.Contains(groupName))
            {
                throw new System.Exception($"存在{groupName}的组");
            }
            Group group = new Group(groupName, true);
            groupDict.SetAt(groupName, group);
            trans.AddNewlyCreatedDBObject(group, true);
            group.Append(new ObjectIdCollection(ids));

            return group;
        }

        /// <summary>
        /// 移除组名
        /// </summary>
        /// <param name="db">dwg数据库</param>
        /// <param name="groupName">组名称</param>
        public static void RemoveGroup(this Database db, string groupName)
        {
            Transaction trans = db.TransactionManager.TopTransaction;
            DBDictionary groupDict = (DBDictionary)trans.GetObject(db.GroupDictionaryId, OpenMode.ForWrite);

            if (groupDict.Contains(groupName))
            {
                Group g = trans.GetObject(groupDict.GetAt(groupName), OpenMode.ForWrite) as Group;
                groupDict.Remove(groupName);
                g.Erase();
            }
        }

        /// <summary>
        /// 得到组
        /// </summary>
        /// <param name="db">dwg数据库</param>
        /// <param name="groupName">组名称</param>
        /// <param name="mode">打开模式</param>
        /// <returns>组</returns>
        public static Group GetGroup(this Database db, string groupName, OpenMode mode)
        {
            Transaction trans = db.TransactionManager.TopTransaction;
            DBDictionary groupDict = (DBDictionary)trans.GetObject(db.GroupDictionaryId, OpenMode.ForRead);

            if (groupDict.Contains(groupName))
            {
                return trans.GetObject(groupDict.GetAt(groupName), mode) as Group;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 实体所在组集合
        /// </summary>
        /// <param name="obj">实体</param>
        /// <param name="mode">打开模式</param>
        /// <returns>组集合</returns>
        public static IEnumerable<Group> GetGroups(this DBObject obj, OpenMode mode)
        {
            Transaction trans = obj.Database.TransactionManager.TopTransaction;
            return obj.GetPersistentReactorIds().Cast<ObjectId>().Select(x => trans.GetObject(x, mode)).OfType<Group>();
        }

        /// <summary>
        /// 得到所有组集合
        /// </summary>
        /// <param name="db">dwg数据库</param>
        /// <param name="mode">打开模式</param>
        /// <returns>组集合</returns>
        public static IEnumerable<Group> GetGroups(this Database db, OpenMode mode)
        {
            Transaction trans = db.TransactionManager.TopTransaction;
            DBDictionary groupDict = (DBDictionary)trans.GetObject(db.GroupDictionaryId, OpenMode.ForRead);

            return groupDict.Cast<DictionaryEntry>().Select(x => trans.GetObject((ObjectId)x.Value, mode)).Cast<Group>();
        }
    }
}
